namespace EyeOpen.TransparentLabel.Windows
{
	using System;
	using System.Drawing;
	using System.Windows.Forms;

	public class TransparentLabel : Control
	{
		private ContentAlignment textAlign = ContentAlignment.TopLeft;

		public TransparentLabel()
		{
			TabStop = false;
			Speed = 3;
		}

		public byte Speed { get; set; }

		public override string Text
		{
			get
			{
				return base.Text;
			}

			set
			{
				base.Text = value;
				RecreateHandle();
			}
		}

		public override RightToLeft RightToLeft
		{
			get
			{
				return base.RightToLeft;
			}

			set
			{
				base.RightToLeft = value;
				RecreateHandle();
			}
		}

		public override Font Font
		{
			get
			{
				return base.Font;
			}

			set
			{
				base.Font = value;
				RecreateHandle();
			}
		}

		public ContentAlignment TextAlign
		{
			get
			{
				return textAlign;
			}

			set
			{
				textAlign = value;
				RecreateHandle();
			}
		}

		public override Color ForeColor
		{
			get
			{
				return base.ForeColor;
			}

			set
			{
				base.ForeColor = value;
				RecreateHandle();
			}
		}

		protected override CreateParams CreateParams
		{
			get
			{
				var cp = base.CreateParams;
				cp.ExStyle |= 0x20;
				return cp;
			}
		}

		/// <exception cref="Exception">Speed cannot be 0.</exception>
		public void AnimatedHide()
		{
			if (Speed == 0)
			{
				throw new Exception("Speed cannot be 0.");
			}

			var color = ForeColor;

			var timer = new Timer { Interval = 1 };

			var alpha = 255;

			timer.Tick
				+= (s, e) =>
				{
					alpha -= Speed;
					ForeColor = Color.FromArgb(alpha, color);

					if (alpha > 0)
					{
						return;
					}

					Hide();

					timer.Stop();
					timer.Dispose();
				};

			timer
				.Start();
		}

		protected override void OnPaintBackground(PaintEventArgs e)
		{
		}

		protected override void OnPaint(PaintEventArgs e)
		{
			Draw();
		}

		protected override void WndProc(ref Message m)
		{
			base.WndProc(ref m);

			if (m.Msg == 0x000F)
			{
				Draw();
			}
		}

		private void Draw()
		{
			using (var graphics = CreateGraphics())
			{
				using (var brush = new SolidBrush(ForeColor))
				{
					var size = graphics.MeasureString(Text, Font);

					float top = 0;

					switch (textAlign)
					{
						case ContentAlignment.MiddleLeft:
						case ContentAlignment.MiddleCenter:
						case ContentAlignment.MiddleRight:
							top = (Height - size.Height) / 2;
							break;
						case ContentAlignment.BottomLeft:
						case ContentAlignment.BottomCenter:
						case ContentAlignment.BottomRight:
							top = Height - size.Height;
							break;
					}

					float left = -1;
					switch (textAlign)
					{
						case ContentAlignment.TopLeft:
						case ContentAlignment.MiddleLeft:
						case ContentAlignment.BottomLeft:
							if (RightToLeft == RightToLeft.Yes)
							{
								left = Width - size.Width;
							}
							else
							{
								left = -1;
							}

							break;
						case ContentAlignment.TopCenter:
						case ContentAlignment.MiddleCenter:
						case ContentAlignment.BottomCenter:
							left = (Width - size.Width) / 2;
							break;
						case ContentAlignment.TopRight:
						case ContentAlignment.MiddleRight:
						case ContentAlignment.BottomRight:
							if (RightToLeft == RightToLeft.Yes)
							{
								left = -1;
							}
							else
							{
								left = Width - size.Width;
							}

							break;
					}

					graphics.DrawString(Text, Font, brush, left, top);
				}
			}
		}
	}
}